package com.thinkgem.jeesite.common.web;

import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.thinkgem.jeesite.common.utils.DateUtils;
import com.thinkgem.jeesite.modules.sys.utils.ResponseEnum;
import com.thinkgem.jeesite.modules.sys.utils.ResponseObject;

import org.apache.commons.lang3.StringEscapeUtils;


@ControllerAdvice
public class GlobalControllerAdvice {
	/**
	 * 日志对象
	 */
	protected Logger logger = LoggerFactory.getLogger(getClass());
	/**
	 * 参数绑定多异常 或校验异常
	 */
	@ResponseBody
	@ExceptionHandler({BindException.class,ConstraintViolationException.class})
	public ResponseObject<Set<String>> bindException(Exception e){
		Set<String> errMsg = new HashSet<String>();
		if (e instanceof BindException) {
			logger.info("参数绑定异常："+e.getMessage());
			List<ObjectError> allError = ((BindException)e).getAllErrors();
			for (ObjectError objectError : allError) {
				logger.info(objectError.getDefaultMessage());
				errMsg.add(objectError.getDefaultMessage());
			}
		}
		if (e instanceof ConstraintViolationException ) {
			logger.info("参数绑定异常："+e.getMessage());
			Set<ConstraintViolation<?>> violations = ((ConstraintViolationException)e).getConstraintViolations();
			for (ConstraintViolation<?> violation : violations) {
				logger.info(violation.getMessage());
				errMsg.add(violation.getMessage());
			}
		}
		ResponseObject<Set<String>> responseObject = new ResponseObject<>(ResponseEnum.validate_error);
		responseObject.setData(errMsg);
		return responseObject;
	}
	
	/**
	 * 登录异常
	 */
	@ResponseBody
	@ExceptionHandler({AuthorizationException.class})
	public ResponseObject<?> unauthenticationException(Exception e,HttpServletRequest request){
		 logger.info("URI[{}]权限不足",request.getRequestURI());
		 e.printStackTrace();
		 return ResponseObject.failResponse(ResponseEnum.authority_error);
	}
	
	/**
	 * 缺少参数异常
	 */
	@ResponseBody
	@ExceptionHandler({MissingServletRequestParameterException.class})
	public ResponseObject<?> bussinessErrorHandler(MissingServletRequestParameterException e){
		 logger.info("参数缺失 ："+e.getMessage());
		 e.printStackTrace();
		 ResponseObject<String> responseObject = new ResponseObject<String>(ResponseEnum.validate_error);
		 responseObject.setMessage("参数 ："+e.getParameterName()+" 缺失");
		 return responseObject;
	}
	
	/**
	 * 捕获代码中手动抛出的异常
	 */
	@ResponseBody
	@ExceptionHandler({BusinessException.class})
	public ResponseObject<?> bussinessErrorHandler(BusinessException e){
		 logger.info("业务逻辑异常 ："+e.getMessage());
		 e.printStackTrace();
		 ResponseObject<String> responseObject = new ResponseObject<String>(e.getCode(),e.getMessage());
		 return responseObject;
	}
	
	/**
	 * 通用异常处理 ，捕获代码中手动抛出的异常
	 */
	@ResponseBody
	@ExceptionHandler({Exception.class})
	@ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR)
	public ResponseObject<?> httpException(HttpServletRequest request,Exception e){
		 logger.info("URI : "+request.getRequestURI());
		 logger.info("系统异常 ："+ e.getMessage());
		 e.printStackTrace();
		 ResponseObject<String> responseObject = new ResponseObject<String>(ResponseEnum.sys_error);
		 return responseObject;
	}
	/**
	 * 
	 * @Title: initBinder   
	 * @Description:  初始化数据绑定
	 *   将所有传递进来的String 进行Html编码 防止xss攻击
	 *   将所有的Date类型转换成String类型
	 * @param: @param binder      
	 * @return: void      
	 * @throws
	 */
	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		binder.registerCustomEditor(String.class, new PropertyEditorSupport(){
			/*字符创类型转换*/
			@Override
			public String getAsText() {
				Object value = getValue();
				return value != null ? value.toString() : ""; 
			}

			@Override
			public void setAsText(String text) throws IllegalArgumentException {
				 setValue(text == null ? null :StringEscapeUtils.escapeHtml4(text.trim()));
			}
			
		});
		/*Date类型转化*/
		binder.registerCustomEditor(Date.class, new PropertyEditorSupport(){
			@Override
			public void setAsText(String text) throws IllegalArgumentException {
				 setValue(DateUtils.parseDate(text));
			}
		});
	}
	
}
